package com.mdd.admin.service.coupon.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.admin.service.common.IAlbumService;
import com.mdd.admin.service.coupon.ICouponService;
import com.mdd.admin.validate.common.PageParam;
import com.mdd.admin.validate.coupon.CouponShareValidate;
import com.mdd.admin.validate.coupon.CouponValidate;
import com.mdd.admin.vo.coupon.*;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.album.Album;
import com.mdd.common.entity.code.CouponCode;
import com.mdd.common.entity.coupon.Coupon;
import com.mdd.common.entity.coupon.CouponShare;
import com.mdd.common.entity.coupon.UserCoupon;
import com.mdd.common.entity.refund.OrderRefund;
import com.mdd.common.entity.user.User;
import com.mdd.common.enums.AlbumEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.album.AlbumMapper;
import com.mdd.common.mapper.coupon.CouponCodeMapper;
import com.mdd.common.mapper.coupon.CouponMapper;
import com.mdd.common.mapper.coupon.CouponShareMapper;
import com.mdd.common.mapper.coupon.UserCouponMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.plugin.storage.StorageDriver;
import com.mdd.common.utils.StringUtil;
import com.mdd.common.utils.TimeUtil;
import javafx.scene.input.DataFormat;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
@Log4j2
public class CouponServiceImpl implements ICouponService {

	@Resource
	private CouponMapper couponMapper;

	@Resource(name = "taskExecutor")
	private Executor executor;

	@Resource
	private CouponCodeMapper couponCodeMapper;

	@Resource
	private UserCouponMapper userCouponMapper;

	@Resource
	private UserMapper userMapper;

	@Resource
	private IAlbumService iAlbumService;

	@Resource
	private RedisTemplate redisTemplate;

	@Resource
	private RestTemplate restTemplate;

	@Value("${wx.qr.generationUrl}")
	private String url;

	@Value("${wx.qr.accessToken}")
	private String accessTokenUrl;

	@Value("${wx.app.appId}")
	private String appId;

	@Value("${wx.app.secret}")
	private String appSecret;

	@Value("${wx.qr.envProfile}")
	private String envProfile;

	@Resource
	private CouponShareMapper couponShareMapper;
	@Autowired
	private AlbumMapper albumMapper;

	/**
	 * @param params 搜索参数
	 * @return Object
	 */
	@Override
	public PageResult<CouponListVo> list(PageParam pageParam, Map<String, String> params) {
		Integer pageNo = pageParam.getPageNo();
		Integer pageSize = pageParam.getPageSize();

		LambdaQueryWrapper<Coupon> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		queryWrapper.orderByDesc(Coupon::getId);
		Integer type = Integer.parseInt(params.get("type"));  // 设置查询的列表   0 - 全部    1 - 使用中   2 - 已过期    3 - 使用完
		switch (type) {
			case 0:
				break;
			case 1:
				queryWrapper.lt(Coupon::getEndTime, TimeUtil.timestamp());
				queryWrapper.apply("number != claim_count");
				break;
			case 2:
				queryWrapper.gt(Coupon::getEndTime, TimeUtil.timestamp());
				queryWrapper.ne(Coupon::getNumber, 0);
				break;
			case 3:
				queryWrapper.apply("number = claim_count");
				break;
		}

		IPage<Coupon> iPage = couponMapper.selectPage(new Page<>(pageNo, pageSize), queryWrapper);
		ArrayList<CouponListVo> list = new ArrayList<>();
		iPage.getRecords().forEach(item -> {
			CouponListVo vo = new CouponListVo();
			BeanUtils.copyProperties(item, vo);
			// vo.setUsageRateDesc(item.getUsageRate());
			vo.setPromotionMethodDesc(item.getPromotionMethod());
			vo.setStatusDesc(item.getStatus());
			vo.setEditBtn(item.getStatus());
			vo.setDeleteBtn(item.getStatus());
			vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
			vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
			vo.setUsedTime(item.getStartTime(), item.getEndTime());
			list.add(vo);
		});
		long allCount = iPage.getTotal();
		long waitCount = iPage.getRecords().stream().filter(coupon -> coupon.getStatus() == 0).distinct().count();
		long progressCount = iPage.getRecords().stream().filter(coupon -> coupon.getStatus() == 1).distinct().count();
		long endCount = iPage.getRecords().stream().filter(coupon -> coupon.getStatus() == 2).distinct().count();
		Map<String, Long> map = new LinkedHashMap<>();
		map.put("allCount", allCount);
		map.put("waitCount", waitCount);
		map.put("progressCount", progressCount);
		map.put("endCount", endCount);
		return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list, map);
	}

	@Override
	public CouponListCountVo countList() {
		CouponListCountVo couponListCountVo = new CouponListCountVo();
		// 全部
		LambdaQueryWrapper<Coupon> couponLambdaQueryWrapper = new LambdaQueryWrapper<>();
		couponLambdaQueryWrapper.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		Integer all = couponMapper.selectCount(couponLambdaQueryWrapper);// 查询出所有的优惠券
		couponListCountVo.setAll(all);

		// 使用中
		couponLambdaQueryWrapper.lt(Coupon::getEndTime, TimeUtil.timestamp());
		couponLambdaQueryWrapper.apply("number != claim_count");
		Integer inUse = couponMapper.selectCount(couponLambdaQueryWrapper);
		couponListCountVo.setInUse(inUse);

		// 过期
		LambdaQueryWrapper<Coupon> couponLambdaQueryWrapperCount = new LambdaQueryWrapper<>();
		couponLambdaQueryWrapperCount.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		couponLambdaQueryWrapperCount.gt(Coupon::getEndTime, TimeUtil.timestamp());
		couponLambdaQueryWrapperCount.ne(Coupon::getNumber, 0);
		Integer expired = couponMapper.selectCount(couponLambdaQueryWrapperCount);
		couponListCountVo.setExpired(expired);

		// 使用完
		LambdaQueryWrapper<Coupon> couponLambda = new LambdaQueryWrapper<>();
		couponLambda.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		couponLambda.apply("number = claim_count"); // 比较总数量和领取数量是否相等
		Integer useUp = couponMapper.selectCount(couponLambda);
		couponListCountVo.setUseUp(useUp);

		return couponListCountVo;
	}

	@Override
	public CouponDetailVo detail(Integer id) {
		CouponDetailVo couponDetailVo = new CouponDetailVo();
		Coupon coupon = couponMapper.selectById(id);
		BeanUtil.copyProperties(coupon, couponDetailVo);
		LambdaQueryWrapper<UserCoupon> queryWrapper1 = new LambdaQueryWrapper<>();
		queryWrapper1.eq(UserCoupon::getCouponId, id);
		Integer i = userCouponMapper.selectCount(queryWrapper1);
//        couponDetailVo.setServices(Arrays.asList(coupon.getService().substring(1, coupon.getService().length() - 1).split(",")));
		couponDetailVo.setRemaining(coupon.getNumber() - i);  // 设置剩余数量
		couponDetailVo.setStartTime(TimeUtil.timestampToDate(coupon.getStartTime()));
		couponDetailVo.setEndTime(TimeUtil.timestampToDate(coupon.getEndTime()));
		LambdaQueryWrapper<UserCoupon> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(UserCoupon::getIsDelete, GlobalConstant.NOT_DELETE);
		queryWrapper.eq(UserCoupon::getCouponId, id);
		List<UserCoupon> userCoupons = userCouponMapper.selectList(queryWrapper);

		List<UserCouponVo> list = new ArrayList<>();
		userCoupons.forEach(userCoupon -> {
			UserCouponVo userCouponVo = new UserCouponVo();
			User user = userMapper.selectById(userCoupon.getUserId());
			if(user != null) {
//				userCouponVo.setImage(user.getAvatar());
				userCouponVo.setUsername(user.getNickname());
			} else {
				return;
			}
			userCouponVo.setUseTime(TimeUtil.timestampToDate(userCoupon.getUpdateTime()));
			userCouponVo.setIsUsed(userCoupon.getIsUsed());
			list.add(userCouponVo);
		});
		couponDetailVo.setUseUser(list);

		LambdaQueryWrapper<CouponCode> couponCodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
		couponCodeLambdaQueryWrapper.eq(CouponCode::getCouponId, id);
		List<String> collect = couponCodeMapper.selectList(couponCodeLambdaQueryWrapper).stream().map(CouponCode::getCouponCode).collect(Collectors.toList());
		couponDetailVo.setCouponCodes(collect);
		return couponDetailVo;
	}

	/**
	 * @param couponValidate 优惠券参数
	 */
	@Override
	public void create(CouponValidate couponValidate) {
		Long startTime = null;
		Long endTime = null;
		Long nowTime =  new Date().getTime();
		switch (couponValidate.getUseTime()) {
			case 0:
				Assert.isTrue(!StringUtil.isEmpty(couponValidate.getStartTime()), "开始日期不能为空！");
				Assert.isTrue(!StringUtil.isEmpty(couponValidate.getEndTime()), "结束日期不能为空！");
				startTime = TimeUtil.dateToTimestamp(couponValidate.getStartTime());
				endTime = TimeUtil.dateToTimestamp(couponValidate.getEndTime());
				break;
			case 1:
				Assert.isTrue(couponValidate.getUseDay() > 0, "使用时间错误！");
				startTime = TimeUtil.timestamp();
				endTime = startTime + (86400 * Long.valueOf(couponValidate.getUseDay()));
				break;
			case 2:
				Assert.isTrue(couponValidate.getUseDay() > 0, "使用时间错误！");
				startTime = TimeUtil.timestamp() + (86400 * 1L);
				endTime = startTime + (86400 * Long.valueOf(couponValidate.getUseDay()));
		}
		Coupon model = new Coupon();
		model.setName(couponValidate.getName());
		model.setContent(couponValidate.getContent());
		model.setAmount(couponValidate.getAmount());
		model.setMetAmount(couponValidate.getConditions() == 0 ? BigDecimal.ZERO : couponValidate.getMetAmount());
		model.setPromotionMethod(couponValidate.getPromotionMethod());
		model.setNumber(couponValidate.getNumber());     // 设置发放数量
		model.setConditions(couponValidate.getConditions());  // 设置使用门槛， 需要满足多少钱使用
		model.setUseRange(couponValidate.getUseRange());
		model.setService(couponValidate.getService().toString());
		model.setStatus(nowTime > startTime?1:0);
		model.setClaim(couponValidate.getClaim());
		model.setClaimCount(couponValidate.getClaim() == 0 ? 0 : couponValidate.getClaimCount());
		model.setIsDelete(0);
		model.setStartTime(startTime);
		model.setEndTime(endTime);
		model.setCreateTime(TimeUtil.timestamp());
		model.setUpdateTime(TimeUtil.timestamp());
		model.setIsSuperimposing(couponValidate.getIsSuperimposing());   // 叠加
		model.setShareType(couponValidate.getShareType());        // 优惠券类型
		model.setImageAddress(couponValidate.getImageAddress());   // 优惠券图片

		couponMapper.insert(model);
		if(couponValidate.getShareType() == 3) {
			String fileName = "优惠券二维码" + model.getId() + ".png";
			StringBuilder sendUrl = new StringBuilder(url);
			Map<String, Object> requestBody = new HashMap<>();
			requestBody.put("page", "pages/login/login");  // 设置二维码跳转的地址
			requestBody.put("scene", "couponId=" + model.getId());  // 设置优惠券的id
			requestBody.put("auto_color", false);
			requestBody.put("env_version", envProfile);
			Map<String, String> color = new HashMap<>();
			color.put("r", "125");
			color.put("g", "82");
			color.put("b", "132");
			requestBody.put("line_color", color);
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<Map<String, Object>>(requestBody, headers);
			String accessTokenKey = "wx:accessToken";
			// 获取wx的accessToken，如果没有则调用接口获取
			if (redisTemplate.hasKey(accessTokenKey)) {
				sendUrl.append("?access_token=" + redisTemplate.opsForValue().get(accessTokenKey));
			} else {
				String getAccessTokenUrl = accessTokenUrl + "?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
				String forObject = restTemplate.getForObject(getAccessTokenUrl, String.class);
				JSONObject jsonObject = JSONUtil.parseObj(forObject);
				String accessToken = jsonObject.getStr("access_token");
				sendUrl.append("?access_token=" + accessToken);
				redisTemplate.opsForValue().set(accessTokenKey, accessToken, 2, TimeUnit.HOURS);
			}
			byte[] result = restTemplate.postForObject(sendUrl.toString(), httpEntity, byte[].class);
			MultipartFile multipartFile = new MockMultipartFile(fileName, fileName, MimeTypeUtils.IMAGE_PNG_VALUE, result);
			StorageDriver storageDriver = new StorageDriver();
			Map<String, Object> map = storageDriver.upload(multipartFile, "image", AlbumEnum.IMAGE.getCode());
			Map<String, String> album = new LinkedHashMap<>();
			album.put("aid", "0");
			// 设置为4，代表优惠券二维码目录
			album.put("cid", "4");
			album.put("type", String.valueOf(AlbumEnum.IMAGE.getCode()));
			album.put("size", map.get("size").toString());
			album.put("ext", map.get("ext").toString());
			album.put("url", map.get("url").toString());
			album.put("name", map.get("name").toString());
			iAlbumService.albumAdd(album);
		} else {
			// 生成二维码加code， 使用多线程去生成
			executor.execute(new Runnable() {
				@Override
				public void run() {
					for (Integer i = 0; i < couponValidate.getNumber(); i++) {
						CouponCode couponCode = new CouponCode();
						couponCode.setCouponId(model.getId());
						String uuid = UUID.randomUUID(true).toString(true).substring(3, 18);
						couponCode.setCouponCode(uuid);
						String fileName = model.getName() + "二维码_" + model.getId() + "_" + i + ".png";
						StringBuilder sendUrl = new StringBuilder(url);
						Map<String, Object> requestBody = new HashMap<>();
						requestBody.put("page", "pages/login/login");  // 设置二维码跳转的地址
						requestBody.put("scene", "couponCode=" + uuid);  // 设置优惠券的兑换码id实现一码一次
						requestBody.put("auto_color", false);
						requestBody.put("env_version", envProfile);
						Map<String, String> color = new HashMap<>();
						color.put("r", "125");
						color.put("g", "82");
						color.put("b", "132");
						requestBody.put("line_color", color);
						HttpHeaders headers = new HttpHeaders();
						headers.setContentType(MediaType.APPLICATION_JSON);
						HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<Map<String, Object>>(requestBody, headers);
						String accessTokenKey = "wx:accessToken";
						// 获取wx的accessToken，如果没有则调用接口获取
						if (redisTemplate.hasKey(accessTokenKey)) {
							sendUrl.append("?access_token=" + redisTemplate.opsForValue().get(accessTokenKey));
						} else {
							String getAccessTokenUrl = accessTokenUrl + "?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
							String forObject = restTemplate.getForObject(getAccessTokenUrl, String.class);
							JSONObject jsonObject = JSONUtil.parseObj(forObject);
							String accessToken = jsonObject.getStr("access_token");
							Integer expiresIn = jsonObject.getInt("expires_in");
							log.info("请求获取的新的accessToken为： " + accessToken);
							sendUrl.append("?access_token=" + accessToken);
							redisTemplate.opsForValue().set(accessTokenKey, accessToken, expiresIn, TimeUnit.SECONDS);
						}
						byte[] result = restTemplate.postForObject(sendUrl.toString(), httpEntity, byte[].class);
						MultipartFile multipartFile = new MockMultipartFile(fileName, fileName, MimeTypeUtils.IMAGE_PNG_VALUE, result);
						StorageDriver storageDriver = new StorageDriver();
						Map<String, Object> map = storageDriver.upload(multipartFile, "image", AlbumEnum.IMAGE.getCode());
						Map<String, String> album = new LinkedHashMap<>();
						album.put("aid", "0");
						// 设置为4，代表优惠券二维码目录
						album.put("cid", "4");
						album.put("type", String.valueOf(AlbumEnum.IMAGE.getCode()));
						album.put("size", map.get("size").toString());
						album.put("ext", map.get("ext").toString());
						album.put("url", map.get("url").toString());
						album.put("name", map.get("name").toString());
						couponCode.setImageId(iAlbumService.albumAdd(album));
						couponCodeMapper.insert(couponCode);
					}
				}
			});
		}
	}



	@Override
	public void edit(CouponValidate couponValidate) {
		LambdaQueryWrapper<Coupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Coupon::getId, couponValidate.getId());
		lambdaQueryWrapper.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		lambdaQueryWrapper.last("limit 1");
		Coupon model = couponMapper.selectOne(lambdaQueryWrapper);
		Assert.notNull(model, "当前优惠券不存在！");
		Assert.isTrue(model.getStatus() == 0, "优惠券处于未开始或状态才能编辑！");
		Assert.isTrue(couponValidate.getNumber() >= model.getNumber(), "无法减少优惠券数量！");
		//进行编辑处理
		Long startTime = null;
		Long endTime = null;
		switch (couponValidate.getUseTime()) {
			case 0:
				Assert.isTrue(!StringUtil.isEmpty(couponValidate.getStartTime()), "开始日期不能为空！");
				Assert.isTrue(!StringUtil.isEmpty(couponValidate.getEndTime()), "结束日期不能为空！");
				startTime = TimeUtil.dateToTimestamp(couponValidate.getStartTime());
				endTime = TimeUtil.dateToTimestamp(couponValidate.getEndTime());
				break;
			case 1:
				Assert.isTrue(couponValidate.getUseDay() > 0, "使用时间错误！");
				startTime = TimeUtil.timestamp();
				endTime = startTime + (86400 * Long.valueOf(couponValidate.getUseDay()));
				break;
			case 2:
				Assert.isTrue(couponValidate.getUseDay() > 0, "使用时间错误！");
				startTime = TimeUtil.timestamp() + (86400 * 1L);
				endTime = startTime + (86400 * Long.valueOf(couponValidate.getUseDay()));
		}
		model.setName(couponValidate.getName());
		model.setContent(couponValidate.getContent());
		model.setAmount(couponValidate.getAmount());
		model.setMetAmount(couponValidate.getConditions() == 0 ? BigDecimal.ZERO : couponValidate.getMetAmount());
		model.setPromotionMethod(couponValidate.getPromotionMethod());
		model.setNumber(couponValidate.getNumber());     // 设置发放数量
		model.setConditions(couponValidate.getConditions());  // 设置使用门槛， 需要满足多少钱使用
		model.setUseRange(couponValidate.getUseRange());
		model.setService(couponValidate.getService().toString());
		model.setClaim(couponValidate.getClaim());
		model.setClaimCount(couponValidate.getClaim() == 0 ? 0 : couponValidate.getClaimCount());
		model.setIsDelete(0);
		model.setStartTime(startTime);
		model.setEndTime(endTime);
		model.setCreateTime(TimeUtil.timestamp());
		model.setUpdateTime(TimeUtil.timestamp());
		model.setIsSuperimposing(couponValidate.getIsSuperimposing());
		model.setShareType(couponValidate.getShareType());
		model.setImageAddress(couponValidate.getImageAddress());
		couponMapper.updateById(model);
	}

	@Override
	public void delete(Integer id) {
		LambdaQueryWrapper<Coupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Coupon::getId, id);
		lambdaQueryWrapper.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		lambdaQueryWrapper.last("limit 1");
		Coupon model = couponMapper.selectOne(lambdaQueryWrapper);
		Assert.notNull(model, "当前优惠券不存在！");
		Assert.isTrue(model.getStatus() != 1, "优惠券状态处于进行中不能被删除");
		model.setIsDelete(1);
		model.setUpdateTime(TimeUtil.timestamp());
		model.setDeleteTime(TimeUtil.timestamp());
		couponMapper.updateById(model);
	}

	@Override
	public void start(Integer id) {
		LambdaQueryWrapper<Coupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Coupon::getId, id);
		lambdaQueryWrapper.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		lambdaQueryWrapper.last("limit 1");
		Coupon model = couponMapper.selectOne(lambdaQueryWrapper);
		Assert.notNull(model, "当前优惠券不存在！");
		Assert.isTrue(model.getStatus() == 0, "优惠券不处于未开始状态！");
		model.setStatus(1);
		model.setUpdateTime(TimeUtil.timestamp());
		couponMapper.updateById(model);
	}

	@Override
	public void stop(Integer id) {
		LambdaQueryWrapper<Coupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Coupon::getId, id);
		lambdaQueryWrapper.eq(Coupon::getIsDelete, GlobalConstant.NOT_DELETE);
		lambdaQueryWrapper.last("limit 1");
		Coupon model = couponMapper.selectOne(lambdaQueryWrapper);
		Assert.notNull(model, "当前优惠券不存在！");
		Assert.isTrue(model.getStatus() == 1, "优惠券不处于进行中状态！");
		model.setStatus(2);
		model.setUpdateTime(TimeUtil.timestamp());
		couponMapper.updateById(model);
	}

	@Override
	public Map<String, String> getCouponImage(Integer id) {
		LambdaQueryWrapper<CouponCode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(CouponCode::getCouponId, id);
		List<CouponCode> couponCodes = couponCodeMapper.selectList(lambdaQueryWrapper);
		HashMap<String, String> stringStringHashMap = new HashMap<>();
		if(couponCodes.isEmpty()) {
			Album album = albumMapper.selectOne(new LambdaQueryWrapper<Album>()
					.eq(Album::getName, "优惠券二维码" + id + ".png")
					.eq(Album::getCid, 4)
			);
			stringStringHashMap.put(album.getName(), album.getUri());
			return stringStringHashMap;
		}
		couponCodes.forEach(couponCode -> {
			Album album = albumMapper.selectById(couponCode.getImageId());
			stringStringHashMap.put(album.getName(), album.getUri());
		});
		return stringStringHashMap;
	}

	@Override
	public void share(Integer id, List<CouponShareValidate> userIds) {
		Coupon coupon = couponMapper.selectById(id);
		Assert.notNull(coupon, "优惠券不存在");
		if (coupon.getShareType() != 2 && coupon.getShareType() != 1) {
			throw new OperateException("该优惠券不支持分享");
		}
		// 计算userIds中的number的和
		Integer number = userIds.stream().map(CouponShareValidate::getNumber).reduce(0, Integer::sum);
		if (coupon.getNumber() - number < 0) {
			throw new OperateException("分配数量失败");
		}
		LambdaQueryWrapper<CouponShare> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(CouponShare::getCouponId, id);
		queryWrapper.eq(CouponShare::getIsDelete, GlobalConstant.NOT_DELETE);
		HashMap<String, Integer> i = new HashMap<>();
		i.put("number", 0);
		userIds.forEach(couponShareValidate -> {
			if (Objects.isNull(couponShareValidate.getUserId())) {
				return;
			}
			queryWrapper.eq(CouponShare::getUserId, couponShareValidate.getUserId());
			CouponShare couponShare = couponShareMapper.selectOne(queryWrapper);
			if (Objects.isNull(couponShare)) {
				CouponShare couponShare1 = new CouponShare();
				couponShare1.setCouponId(id);
				couponShare1.setUserId(couponShareValidate.getUserId());
				couponShare1.setNumber(couponShareValidate.getNumber());
				couponShare1.setCreateTime(TimeUtil.timestamp());
				couponShare1.setUpdateTime(TimeUtil.timestamp());
				couponShare1.setIsDelete(0);
				couponShareMapper.insert(couponShare1);
			} else {
				couponShare.setNumber(couponShareValidate.getNumber());
				couponShare.setUpdateTime(TimeUtil.timestamp());
				couponShareMapper.updateById(couponShare);
			}
			couponCodeMapper.updateByCouponId(id, couponShareValidate.getUserId(), i.get("number"), couponShareValidate.getNumber());
			i.put("number", i.get("number") + couponShareValidate.getNumber());
		});
	}

	@Override
	public List<CouponShareVo> shareList(Map<String, String> params) {
		String s = params.get("id");
		List<CouponShare> couponShares = couponShareMapper.selectList(new LambdaQueryWrapper<CouponShare>().eq(CouponShare::getCouponId, s));
		// 使用stream遍历couponShares
		ArrayList<CouponShareVo> couponShareVos = new ArrayList<>();
		couponShares.stream().forEach(couponShare -> {
			CouponShareVo couponShareVo = new CouponShareVo();
			User user = userMapper.selectById(couponShare.getUserId());
			if (Objects.nonNull(user)) {
				couponShareVo.setUserName(user.getNickname());
			}
			BeanUtil.copyProperties(couponShare, couponShareVo);
			couponShareVos.add(couponShareVo);
		});

		return couponShareVos;
	}

	/**
	 * 每天凌晨，更新优惠券状态
	 */
	public void couponConfirm() {
		log.info("couponConfirm 被执行......");
		// 判断优惠卷活动是否到期
		List<Coupon> refundInfoList = couponMapper.selectList(new LambdaQueryWrapper<Coupon>().eq(Coupon::getIsDelete,GlobalConstant.NOT_DELETE));
		for (Coupon coupon : refundInfoList) {
			Integer status = coupon.getStatus();
			Long startTime = coupon.getStartTime();
			Long endTime = coupon.getEndTime();
			Long nowTime = new Date().getTime();
			status = startTime<nowTime&&nowTime<endTime?1:nowTime>endTime?2:0;
			coupon.setStatus(status);
			couponMapper.updateById(coupon);
		}
	}

}